/*
 * Firewall.c
 *
 *  Created on: May 2, 2013
 *      Author: hezhuobin
 */

#include "SysLib.h"
#include "Firewall.h"

#define IP_PROTO 9

PBitSet tcp_ports = NULL;
PBitSet udp_ports = NULL;


void firewall_allow_port(int protocol, int port) {
    if (port < 0 || port > 65535) return;
    if (protocol == IP_PROTO_TCP) {
        if (!tcp_ports) {
            tcp_ports = bitset_new(65537);
        }
        bitset_set(tcp_ports, port, true);
    } else if (protocol == IP_PROTO_UDP) {
        if (!udp_ports) {
            udp_ports = bitset_new(65537);
        }
        bitset_set(udp_ports, port, true);
    }
}


void do_init_firewall_ports(char* ports, int protocal) {
    char *iter = ports;
    for (;;) {
        char *tail = strchr(iter, ',');
        if (tail == NULL) break;
        tail[0] = '\0';
        firewall_allow_port(protocal, str2int(iter));
        iter = tail + 1;
        tail[0] = ',';
    }
    firewall_allow_port(protocal, str2int(iter));
}

unsigned int get_uint16(unsigned char *raw) {
    return ((unsigned int) raw[0]) << 8 | ((unsigned int) raw[1]);
}

bool filter_upstream_pack(unsigned char * pack, int size, PTunnel tunnel) {
    if (size < 20) return false;
    int i=0;
    for (i=0; i<4; i++) {
        if (pack[12 + i] != tunnel->client_ip_num[i]) {
            log_error("Block ip packet from: %u.%u.%u.%u, to: %u.%u.%u.%u, protocal: %u",
                    pack[12], pack[13], pack[14], pack[15],
                    pack[16], pack[17], pack[18], pack[19],
                    pack[IP_PROTO]);
            return false;
        }
    }
//    if (pack[16] == 192 && pack[17] == 168) {
//        return true;
//    }
//    if (pack[16] == 10) {
//        return true;
//    }
//    if (pack[16] == 172 && (pack[17] >= 16 || pack[17] <= 31)) {
//        return true;
//    }
//    int header_size = (pack[0] & 0x0F) * 4;
//    if (size < header_size + 4) return false;
//    if (pack[IP_PROTO] == IP_PROTO_TCP) {
//        int dst_port = get_uint16(pack + header_size + 2);
//        if (dst_port <= 1024) {
//            return true;
//        } else if (tcp_ports && bitset_check(tcp_ports, dst_port)) {
//            return true;
//        } else {
//            log_error("Block tcp packet to %u.%u.%u.%u:%d",
//                    pack[16], pack[17], pack[18], pack[19], dst_port);
//            return false;
//        }
//    } else if (pack[IP_PROTO] == IP_PROTO_UDP) {
//        int dst_port = get_uint16(pack + header_size + 2);
//        if (dst_port <= 1024) {
//            return true;
//        } else if (udp_ports && bitset_check(udp_ports, dst_port)) {
//            return true;
//        } else {
//            log_error("Block udp packet to %u.%u.%u.%u:%d",
//                    pack[16], pack[17], pack[18], pack[19], dst_port);
//            return false;
//        }
//    }
    return true;
}
